package org.aphelie.romancer.util.message.impl;

import java.io.File;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;

import org.aphelie.romancer.util.message.MessageBundle;
import org.aphelie.romancer.util.message.Messager;
import org.eclipse.core.runtime.Plugin;

public class MessagerImpl implements Messager {
	
	private final String DEFAULT_ERROR_PREFIX = "ATR";
	
    private Map<String, MessageBundle> bundles;
    private Map<String, String> caches;
    private Plugin plugin;
    

    public MessagerImpl(Plugin plugin) {
        this.plugin = plugin;
        caches = new HashMap<String, String>();
        bundles = new HashMap<String, MessageBundle>();
    }
    
	private void init() {
		Enumeration<URL> messageBundleUrls = plugin.getBundle().findEntries("/",
				RESOURCE_BUNDLE_NAME + RESOURCE_BUNDLE_EXTENSION, true);
		if (messageBundleUrls == null) {
			System.out.println("No message bundle found in " + plugin.getBundle().getSymbolicName());
			return;
		}
		while (messageBundleUrls.hasMoreElements()) {
			URL url = messageBundleUrls.nextElement();
			
			System.err.println("urltoString" + url.toString().replaceAll(File.separator, "."));
			System.err.println("pack" + plugin.getClass().getPackage());
			
	
		}
		
	}
    
    
    

    /**
     * Returns the message bundle with the given id.
     * @param id the id of the bundle.
     */
    public MessageBundle getMessageBundle(String id) {
        MessageBundle bundle = bundles.get(id);
        if (bundle != null) {
            return bundle;
        }
        return null;
    }

    /**
     * Registers a new message bundle with the given id and the given name.
     * @param id the id of the bundle.
     * @param bundleName the name of the message bundle.
     */
    public void registerMessageBundle(String id, String bundleName) {
        MessagesBundleImpl bundle = new MessagesBundleImpl(bundleName, plugin);
        if (bundle.getResourceBundle() == null) {
            return;
        }
        bundles.put(id, bundle);
    }

    /**
     * Unregisters a message bundle with the given id.
     * @param id the id of the message bundle.
     */
    public void unregisterMessageBundle(String id) {
        bundles.remove(id);
    }

    /**
     * Registers a new message bundle.
     * @param id the id of the bundle.
     * @param messageBundle the message bundle to register.
     */
    public void registerMessageBundle(String id, MessagesBundleImpl messageBundle) {
        bundles.put(id, messageBundle);
    }

    /**
     * Returns the string associated to the specified key. The search is done by
     * iterating over the bundles until the key is found.
     * @param key the key to search.
     */
    public String getString(String key) {
        return getString(key, null);
    }

    /**
     * Returns the string associated to the specified key or the given default
     * value if the key is not found and is not <code>null</code>. The search is done by
     * iterating over the bundles until the key is found.
     * @param key the key to search.
     * @param defaultValue the default value.
     */
    public String getString(String key, String defaultValue) {
        return getFormattedString(key, null, defaultValue);
    }

    /**
     * Returns the formatted string associated to the specified key.
     * If the key is found the associated String is formatted using the
     * <code>java.text.MessageFormat.format(String pattern, Object[] arguments)</code>
     * method. The search is done by iterating over the bundles until the key is found.
     * @param key the key to search
     * @param args an array of objects to be formatted and substitued.
     */
    public String getFormattedString(String key, Object[] args) {
        return getFormattedString(key, args, null);
    }

    /**
     * Returns the formatted string associated to the specified key or
     * the default value if the key is not found and is not <code>null</code>.
     * If the key is found the associated String is formatted using
     * the <code>java.text.MessageFormat.format(String pattern, Object[] arguments)</code> method.
     * The search is done by iterating over the bundles until the key is found.
     * @param key the key to search
     * @param args an array of objects to be formatted and substituted.
     * @param defaultValue the default value.
     */
    public String getFormattedString(String key, Object[] args, String defaultValue) {
        String obj = caches.get(key);
        if (obj != null && args == null) {
            return obj;
        }
        MessageBundle bundle = null;
        Iterator<String> bundleIterator = bundles.keySet().iterator();
        while (bundleIterator.hasNext()) {
            String id = bundleIterator.next();
            bundle = bundles.get(id);
            if (bundle != null) {
                if (args == null) {
                    obj = bundle.getString(key);
                } else {
                    obj = bundle.getFormattedString(key, args);
                }
                if (obj != null) {
                    caches.put(key, obj);
                    return obj;
                }
            }
        }
        return defaultKey(key, defaultValue);
    }

    /**
     * Returns the string associated to the specified key or the given default
     * value if the key is not found and is not <code>null</code>.
     * @param id the id of the message bundle.
     * @param key the key to search.
     * @param defaultValue the default value.
     */
    public String getString(String id, String key, String defaultValue) {
        return getFormattedString(id, key, null, defaultValue);
    }

    /**
     * Returns the formatted string associated to the specified key or
     * the default value if the key is not found and is not <code>null</code>.
     * If the key is found the associated String is formatted using
     * the <code>java.text.MessageFormat.format(String pattern, Object[] arguments)</code> method.
     * @param id the id of the message bundle.
     * @param key the key to search
     * @param args an array of objects to be formatted and substitued.
     * @param defaultValue the default value.
     */
    public String getFormattedString(String id, String key, Object[] args, String defaultValue) {
        String obj = caches.get(key);
        if (obj != null && args == null) {
            return obj;
        }
        MessageBundle bundle = bundles.get(id);
        if (bundle != null) {
            if (args == null) {
                obj = bundle.getString(key);
            } else {
                obj = bundle.getFormattedString(key, args);
            }
            if (obj != null) {
                caches.put(key, obj);
                return obj;
            }
        }
        return defaultKey(key, defaultValue);
    }

	@Override	
    public String getErrorString(String key) {
        if (hasErrorKey(key)) {
            return key + " : " + getString(key);
        } else {
            return getString(key + "_msgid") + " : " + getString(key);
        }
    }
	@Override
    public String getFormattedErrorString(String key, Object[] args) {
        if (hasErrorKey(key)) {
            return key + " : " + getFormattedString(key, args);
        } else {
            return getString(key + "_msgid") + " : " + getFormattedString(key, args);
        }
    }
    
    private boolean hasErrorKey(String key) {
    	return key.startsWith(DEFAULT_ERROR_PREFIX);
    }
        
    /**
     * Returns the key surrounded by '!' or the default value if it is not <code>null</code>.
     * @param key the key to format.
     * @param defaultValue the default value.
     */
    private String defaultKey(String key, String defaultValue) {
        return defaultValue != null ? defaultValue : "!" + key + "!"; //No i18N
    }

}
